Many commercial finite element codes provide an interface that allows users to implement general material constitutive equations. A user material model:
is used to define the mechanical constitutive behavior of a material;
is called at integration points of elements for which the material definition includes a user-defined material behavior;
can use solution-dependent state variables;
updates the stresses and solution-dependent state variables to their values at the end of the increment for which it is called;
for most implicit solvers must provide the material Jacobian matrix, $\partial\Delta\pmb{\sigma}/\partial\Delta\pmb{\epsilon}$;
Use the user material interface only when none of the existing material models included in the code's material library accurately represents the behavior of the material to be modeled.
Requires one of the following:
It is also likely to require:
Use a suitable integration procedure (this is the hard part!):
Forward Euler (explicit integration)
Simple to implement, but has a stability limit
$$\Delta\epsilon < \Delta\epsilon_{\rm stab}$$
where $\Delta\epsilon_{\rm stab}$ is usually less than the elastic strain magnitude.
Backward Euler (implicit integration)
Midpoint method
For small-deformation problems (e.g., linear elasticity) or large-deformation problems with small volume changes (e.g., metal plasticity), the consistent Jacobian is
$$ \mathbb{C} = \frac{\partial\Delta\pmb{\sigma}}{\partial\Delta\pmb{\epsilon}}$$
where $\Delta\sigma$ is the increment in stress and $\Delta\epsilon$ is the increment in strain.
If large deformations with large volume changes are considered (e.g., pressure-dependent plasticity), the exact form of the consistent Jacobian
$$ \mathbb{C} = \frac{1}{J}\frac{\partial\Delta\left(J\pmb{\sigma}\right)}{\partial\Delta\pmb{\epsilon}}$$
should be used to ensure rapid convergence.
For hyperelastic constitutive equations, in which $\pmb{\sigma}$ is a proper function of the deformation, the consistent Jacobian is defined by:
$$\delta\left(J\pmb{\sigma}\right) = J\mathbb{C}{:}\delta\pmb{d}$$
∗DEPVAR option.In Abaqus, run tests with all displacements prescribed to verify the integration algorithm for stresses and state variables.
Suggested tests include:
Run similar tests with load prescribed to verify the accuracy of the Jacobian.
sqa_stiff option to compare stiffness to that computed numericallySUBROUTINE UMAT(STRESS, STATEV, DDSDDE, SSE, SPD, SCD, RPL,
1 DDSDDT, DRPLDE,DRPLDT,STRAN,DSTRAN,TIME,DTIME,TEMP,DTEMP,
2 PREDEF,DPRED, CMNAME, NDI, NSHR, NTENS, NSTATV, PROPS, NPROPS,
3 COORDS, DROT, PNEWDT, CELENT, DFGRD0, DFGRD1, NOEL, NPT, LAYER,
4 KSPT, KSTEP, KINC)
INCLUDE 'ABA_PARAM.INC'
CHARACTER*8 CMNAME
DIMENSION STRESS(NTENS), STATEV(NSTATV), DDSDDE(NTENS, NTENS),
1 DDSDDT(NTENS), DRPLDE(NTENS), STRAN(NTENS), DSTRAN(NTENS),
2 PREDEF(1), DPRED(1), PROPS(NPROPS), COORDS(3), DROT(3, 3),
3 DFGRD0(3, 3), DFGRD1(3, 3)
implicit none is used, make sure the precision set matches that of AbaqusThe following quantities are available in UMAT:
The following quantities must be defined:
The following variables may be defined:
A complete description of all parameters is given in the Abaqus user subroutines guide
SINV will return the first and second invariants of a tensor.SPRINC will return the principal values of a tensor.SPRIND will return the principal values and directions of a tensor.ROTSIG will rotate a tensor with an orientation matrix.XIT will terminate an analysis and close all files associated with the analysis properly.STD_ABQERR sends messages to Abaqus to write to output filesFor more details, see the Abaqus user subroutines guide
Sresses and strains are stored as vectors
The shear strain is stored as engineering shear strain
$$\gamma_{ij} = 2\epsilon_{ij}, \quad i\ne j$$The deformation gradient, $F_{ij}$, is always stored as a three-dimensional matrix
For geometrically nonlinear analysis the strain increment and incremental rotation passed into the routine are based on the Hughes-Winget formulae.
The user must define the Cauchy stress: when this stress reappears during the next increment, it will have been rotated with the incremental rotation, DROT, passed into the subroutine.
ROTSIG if this is not desired.If the ∗Orientation option is used in conjunction with UMAT, stress and strain components will be in the local system (again, this basis system rotates with the material in finite-strain analysis).
Tensor state variables must be rotated in the subroutine (use ROTSIG).
At the start of a new increment, the strain increment is extrapolated from the previous increment.
∗STEP, EXTRAPOLATION=NOIf the strain increment is too large, the variable PNEWDT can be used to suggest a reduced time increment.
PNEWDT*DTIME.The characteristic element length can be used to define softening behavior based on fracture energy concepts.
Constitutive law:
$$\pmb{\sigma} = 3K{\rm iso}\pmb{\epsilon} + 2G{\rm dev}\pmb{\epsilon}$$
Jaumann (corotational) rate form:
$$\dot{\pmb{\sigma}} = 3K{\rm iso}\dot{\pmb{\epsilon}} + 2G{\rm dev}\dot{\pmb{\epsilon}}$$
The Jaumann rate equation is integrated in a corotational framework:
The appropriate coding is shown in the following cells.
subroutine umat(stress, statev, ddsdde, sse, spd, scd, rpl, &
ddsddt, drplde, drpldt, stran, dstran, time, dtime, temp, dtemp, &
predef, dpred, cmname, ndi, nshr, ntens, nstatv, props, nprops, &
coords, drot, pnewdt, celent, dfgrd0, dfgrd1, noel, npt, layer, &
kspt, kstep, kinc)
implicit none
character*8, intent(in) :: cmname
integer, intent(in) :: ndi, nshr, ntens, nstatv, nprops
integer, intent(in) :: noel, npt, layer, kspt, kstep, kinc
real(8), intent(in) :: sse, spd, scd, rpl, drpldt, time, dtime, temp, dtemp
real(8), intent(in) :: pnewdt, celent
real(8), intent(inout) :: stress(ntens), statev(nstatv), ddsdde(ntens, ntens)
real(8), intent(inout) :: ddsddt(ntens), drplde(ntens)
real(8), intent(in) :: stran(ntens), dstran(ntens)
real(8), intent(in) :: predef(1), dpred(1), props(nprops), coords(3)
real(8), intent(in) :: drot(3, 3), dfgrd0(3, 3), dfgrd1(3, 3)
integer :: i, j
real(8) :: K, K3, G, G2, Lam
character*120 :: msg
character*8 :: charv(1)
integer :: intv(1)
real(8) :: realv(1)
! ------------------------------------------------------------------------- !
implicit none usedif (ndi /= 3) then
msg = 'this umat may only be used for elements &
&with three direct stress components'
call stdb_abqerr(-3, msg, intv, realv, charv)
end if
! elastic properties
K = props(1)
K3 = 3. * K
G = props(2)
G2 = 2. * G
Lam = (K3 - G2) / 3.
! elastic stiffness
ddsdde = 0.
do i=1,ndi
do j = 1,ndi
ddsdde(j,i) = Lam
end do
ddsdde(i,i) = G2 + Lam
end do
do i=ndi+1,ntens
ddsdde(i,i) = G
end do
! stress update
stress = stress + matmul(ddsdde, dstran)
return
end subroutine umat
In [1]:
from matmodlab2 import *
In [2]:
%%writefile umat_elastic.f90
subroutine umat(stress, statev, ddsdde, sse, spd, scd, rpl, &
ddsddt, drplde, drpldt, stran, dstran, time, dtime, temp, dtemp, &
predef, dpred, cmname, ndi, nshr, ntens, nstatv, props, nprops, &
coords, drot, pnewdt, celent, dfgrd0, dfgrd1, noel, npt, layer, &
kspt, kstep, kinc)
implicit none
character*8, intent(in) :: cmname
integer, intent(in) :: ndi, nshr, ntens, nstatv, nprops
integer, intent(in) :: noel, npt, layer, kspt, kstep, kinc
real(8), intent(in) :: sse, spd, scd, rpl, drpldt, time, dtime, temp, dtemp
real(8), intent(in) :: pnewdt, celent
real(8), intent(inout) :: stress(ntens), statev(nstatv), ddsdde(ntens, ntens)
real(8), intent(inout) :: ddsddt(ntens), drplde(ntens)
real(8), intent(in) :: stran(ntens), dstran(ntens)
real(8), intent(in) :: predef(1), dpred(1), props(nprops), coords(3)
real(8), intent(in) :: drot(3, 3), dfgrd0(3, 3), dfgrd1(3, 3)
integer :: i, j
real(8) :: K, K3, G, G2, Lam
character*120 :: msg
character*8 :: charv(1)
integer :: intv(1)
real(8) :: realv(1)
! ------------------------------------------------------------------------- !
if (ndi /= 3) then
msg = 'this umat may only be used for elements &
&with three direct stress components'
call stdb_abqerr(-3, msg, intv, realv, charv)
end if
! elastic properties
K = props(1)
K3 = 3. * K
G = props(2)
G2 = 2. * G
Lam = (K3 - G2) / 3.
! elastic stiffness
ddsdde = 0.
do i=1,ndi
do j = 1,ndi
ddsdde(j,i) = Lam
end do
ddsdde(i,i) = G2 + Lam
end do
do i=ndi+1,ntens
ddsdde(i,i) = G
end do
! stress update
stress = stress + matmul(ddsdde, dstran)
return
end subroutine umat
Note The elastic material model is implemented in free-form Fortran. Matmodlab handles free-form Fortran seemlessly. In Abaqus, the user must inform the Abaqus build system that the material model is implemented in free-form Fortran by adding the
-free(/freeon Windows) flag to thecompile_fortrancommand in theirabaqus_v6.envenvironment file.
Use the build-fext executable to build the material model. The arguments for build-fext are:
build-fext <name> <source files>
if name is umat, build-fext will compile the subroutine against a library providing several Abaqus subroutines (sprind, std_abqerr, etc).
In [3]:
!../bin/build-fext umat umat_elastic.f90
In [4]:
from matmodlab2.umat import UMat
mps = MaterialPointSimulator('job')
K, G = 9.98004e9, 3.75094e9
mps.material = UMat([K, G])
In [5]:
mps.run_step('ESS', (.01,0,0))
Etrue = 9. * K * G / (3. * K + G)
Esim = mps.df['S.XX'].iloc[-1] / mps.df['E.XX'].iloc[-1]
assert abs(Etrue - Esim) / Etrue < 1e-6
In [6]:
mps = MaterialPointSimulator('job')
mps.material = UMat([K, G])
mps.run_step('E', (.01,0,0))
Htrue = K + 4. * G / 3.
Hsim = mps.df['S.XX'].iloc[-1] / mps.df['E.XX'].iloc[-1]
assert abs(Htrue - Hsim) / Htrue < 1e-6